from collections import defaultdict
from itertools import cycle

from termcolor import cprint

from src.bean.database_file_enum import DatabaseFileEnum
from src.bean.model_database_enum import ModelDatabaseEnum
from src.util.common_util import printx
from src.util.config_manager import ConfigManager


def get_model_value(item, value, default: any = "(无)"):
    if value in item:
        return item[value]
    else:
        return default


def get_descendants(model, children_map):
    descendants = []
    stack = [model]
    while stack:
        parent = stack.pop()
        children = children_map.get(parent[ModelDatabaseEnum.id.value], [])
        descendants.extend(children)
        stack.extend(children)
    return descendants


def classify_models(model_list):
    model_dict = {item[ModelDatabaseEnum.id.value]: item for item in model_list}
    children_map = defaultdict(list)
    for item in model_list:
        parent_id = item[ModelDatabaseEnum.increasing_base_on.value]
        if parent_id in model_dict:
            children_map[parent_id].append(item)
    model_id_set = set(model_dict.keys())
    classified_models = []
    for model in model_list:
        if model[
            ModelDatabaseEnum.increasing_base_on.value] not in model_id_set:  # 如果 increasing_base_on 不在 ID 列表里，则为初代模型
            family = [model] + get_descendants(model, children_map)
            classified_models.append(family)
    return classified_models


def print_model_list_entrance(config: ConfigManager) -> None:
    """
    打印模型
    """
    model_list = config.get_model_list()
    cprint("  " * 60, on_color="on_black")
    color_cycle = cycle(["red",
                         "green",
                         "blue",
                         "magenta",
                         "cyan",
                         "light_grey",
                         "dark_grey",
                         "light_red",
                         "light_green",
                         "light_blue",
                         "light_magenta",
                         "light_cyan", ])
    races = classify_models(model_list)
    for race in races:
        color = next(color_cycle)
        desc_list = []
        for item in race:
            files = get_model_value(item, ModelDatabaseEnum.model_data_files.value, default=[])
            file_str_list = []
            for i, file in enumerate(files):
                path = get_model_value(file, DatabaseFileEnum.path.value)
                normal_count = get_model_value(file, DatabaseFileEnum.normal_count.value)
                abnormal_count = get_model_value(file, DatabaseFileEnum.abnormal_count.value)
                origin_predict_file = get_model_value(file, DatabaseFileEnum.origin_predict_file.value)
                file_str_list.append(
                    f"          文件{i + 1} 正常:{normal_count}|异常:{abnormal_count}|路径:{path}|所预测的原始文件:{origin_predict_file}")
            file_str = '\n'.join(file_str_list)
            desc = "\n".join([
                f"模型信息          |id:{get_model_value(item, ModelDatabaseEnum.id.value)}|名称:{get_model_value(item, ModelDatabaseEnum.model_name.value)}|模型描述:{get_model_value(item, ModelDatabaseEnum.model_description.value)}|采样方式:{get_model_value(item, ModelDatabaseEnum.sample_type.value)}|聚类方式:{get_model_value(item, ModelDatabaseEnum.cluster.value)}|生成时间:{get_model_value(item, ModelDatabaseEnum.train_time.value)}|正常样本:{sum(file[DatabaseFileEnum.normal_count.value] for file in files)}条|异常样本:{sum(file[DatabaseFileEnum.abnormal_count.value] for file in files)}条",
                f"基于(增量于)模型  |id:{get_model_value(item, ModelDatabaseEnum.increasing_base_on.value)}",
                f"模型位置          |{get_model_value(item, ModelDatabaseEnum.model_path.value)}",
                f"所用文件\n{file_str}",
                f"模型评估          |测试集占比:{get_model_value(item, ModelDatabaseEnum.test_size.value)}|召回率:{get_model_value(item, ModelDatabaseEnum.recall.value)}|准确率:{get_model_value(item, ModelDatabaseEnum.accuracy.value)}|精确率:{get_model_value(item, ModelDatabaseEnum.precision.value)}|f1:{get_model_value(item, ModelDatabaseEnum.f1.value)}",
                f"超参数            |网格搜索:{get_model_value(item, ModelDatabaseEnum.is_grid_search.value)}|决策树:{get_model_value(item, ModelDatabaseEnum.iterations.value)}|树深度:{get_model_value(item, ModelDatabaseEnum.depth.value)}|学习率:{get_model_value(item, ModelDatabaseEnum.learning_rate.value)}|评估方法:{get_model_value(item, ModelDatabaseEnum.eval_metric.value)}|use_best_model:{get_model_value(item, ModelDatabaseEnum.use_best_model.value)}",
            ])
            desc_list.append((desc, color))

        for desc, color in desc_list:
            cprint(desc, color=color)
            cprint("--" * 60, color="light_grey")
    printx(f"{len(races)}个模型族；共{len(model_list)}个模型")
    cprint("  " * 60, on_color="on_black")
